package cn.zhiquxing.util;

import com.sun.jmx.snmp.tasks.ThreadService;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import java.util.concurrent.*;

public class ThreadUtil {
    
    public static void shutdownThreadPoolGracefully(ExecutorService threadPool) {
        System.out.println("关闭线程池开始");
        // 如果已经关闭则返回
        if (!(threadPool instanceof ThreadService) || threadPool.isTerminated()) {
            return;
        }
        try {
            threadPool.shutdown();
        } catch (SecurityException e) {
            return;
        } catch (NullPointerException e) {
            return;
        }
        
        try {
            //等待60秒，等待线程池中的任务完成执行
            if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {
                // 调用shundownNow()取消正在执行的任务
                threadPool.shutdownNow();
            }
            if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {
                System.out.println("线程池任务未正常执行结束");
            }
        } catch (InterruptedException e) {
            threadPool.shutdownNow();
        }
        // 仍然没有关闭，循环关闭1000次，每次等待10毫秒
        if (!threadPool.isTerminated()) {
            try {
                for (int i = 0; i < 1000; i++) {
                    if (threadPool.awaitTermination(10,  TimeUnit.MILLISECONDS)) {
                        break;
                    }
                    threadPool.shutdownNow();
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
    
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    
    private static final int IO_MAX = Math.max(2, CPU_COUNT * 2);
    /**
     * 空闲保活时限
     */
    private static final int KEEP_ALIVE_SECOND = 30;
    
    
    private static final int QUEUE_SIZE = 128;
    
    public static class IoIntenseTargetThreadPoolLazyHolder {
        private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(IO_MAX, IO_MAX,
                KEEP_ALIVE_SECOND, 
                TimeUnit.SECONDS, 
                new LinkedBlockingQueue<Runnable>(QUEUE_SIZE),
                new CustomizableThreadFactory("io"));
        
        static {
            EXECUTOR.allowCoreThreadTimeOut(true);
            Runtime.getRuntime().addShutdownHook(new ShutdownHookThread("IO密集型任务线程池", new Callable() {
                @Override
                public Object call() throws Exception {
                    shutdownThreadPoolGracefully(EXECUTOR);
                    return null;
                }
            }));
        }
    }
    
    private static final int MAX_POOL_SIZE = CPU_COUNT;
    
    
    public static class CpuIntenseTargetThreadPoolLazyHolder {
        public static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(MAX_POOL_SIZE, 
                MAX_POOL_SIZE,
                KEEP_ALIVE_SECOND,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(QUEUE_SIZE),
                new CustomizableThreadFactory("cpu"));

        static {
            EXECUTOR.allowCoreThreadTimeOut(true);
            Runtime.getRuntime().addShutdownHook(new ShutdownHookThread("CPU密集型任务线程池", new Callable() {
                @Override
                public Object call() throws Exception {
                    shutdownThreadPoolGracefully(EXECUTOR);
                    return null;
                }
            }));
        }
    }
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    static class ShutdownHookThread extends Thread {
        private String mark;
        private Callable callable;
    }
    
    public static class SeqOrScheduledTargetThreadPoolLazyHolder {
        static final ScheduledThreadPoolExecutor EXECUTOR = new ScheduledThreadPoolExecutor(1, new CustomizableThreadFactory("seq"));
        static {
            // 注册jvm关闭时的钩子函数
            Runtime.getRuntime().addShutdownHook(new ShutdownHookThread("定时和顺序任务线程池", new Callable<Void>() {
                @Override
                public Void call() throws Exception {
                    shutdownThreadPoolGracefully(EXECUTOR);
                    return null;
                }
            }));
        }
    }
    
    private static final int MIXED_MAX = 4;
    
    private static final String MIXED_THREAD_AMOUNT = "mixed.thread.amount";

    /**
     * 懒汉式单例创建线程池：用于混合任务
     */
    public static class MixedTargetThreadPoolLazyHolder {
        public static final int max = (null != System.getProperty(MIXED_THREAD_AMOUNT)) ? Integer.parseInt(System.getProperty(MIXED_THREAD_AMOUNT)) : MIXED_MAX;
        public static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(max,
                max,
                KEEP_ALIVE_SECOND,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(QUEUE_SIZE),
                new CustomizableThreadFactory("mixed_"));

        static {
            EXECUTOR.allowCoreThreadTimeOut(true);
            Runtime.getRuntime().addShutdownHook(new ShutdownHookThread("CPU密集型任务线程池", new Callable() {
                @Override
                public Object call() throws Exception {
                    shutdownThreadPoolGracefully(EXECUTOR);
                    return null;
                }
            }));
        }
    }
    
    
    
    
}
